package com.avecsys.quotemanager.service.common;

import java.util.ArrayList;
import java.util.List;

import javax.faces.context.FacesContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.mail.EmailException;
import org.icefaces.ace.json.JSONException;
import org.icefaces.ace.json.JSONObject;

import com.avecsys.quotemanager.constants.ApplicationConstants;
import com.avecsys.quotemanager.constants.ApplicationErrorCodes;
import com.avecsys.quotemanager.dao.common.BaseDAO;
import com.avecsys.quotemanager.dao.common.EnumActor;
import com.avecsys.quotemanager.dao.common.EnumTransactionStatus;
import com.avecsys.quotemanager.exception.BaseException;
import com.avecsys.quotemanager.exception.BusinessException;
import com.avecsys.quotemanager.exception.DAOException;
import com.avecsys.quotemanager.exception.SystemConfigurationException;
import com.avecsys.quotemanager.exception.TechnicalException;
import com.avecsys.quotemanager.pojos.BuyerUsersPojo;
import com.avecsys.quotemanager.pojos.CountryMasterPojo;
import com.avecsys.quotemanager.pojos.SupplierUsersPojo;
import com.avecsys.quotemanager.pojos.SystemUsersPojo;
import com.avecsys.quotemanager.utils.CommonUtils;
import com.avecsys.quotemanager.utils.DateUtils;
import com.avecsys.quotemanager.utils.EmailSender;
import com.avecsys.quotemanager.utils.MessageBoardUtil;
import com.avecsys.quotemanager.utils.SystemConfig;
import com.avecsys.quotemanager.utils.TransactionStatus;

/**
 * 
 * @author Sam Sundar K
 * 
 */
public class CommonServiceImpl implements CommonService {

	private final Log log = LogFactory.getLog(CommonServiceImpl.class);

	private BaseDAO baseDAO;

	/**
	 * @return the baseDAO
	 */
	public BaseDAO getBaseDAO() {
		return baseDAO;
	}

	/**
	 * @param baseDAO
	 *            the baseDAO to set
	 */
	public void setBaseDAO(BaseDAO baseDAO) {
		this.baseDAO = baseDAO;
	}

	/**
	 * Method to return all the Countries
	 * 
	 * @param countryMasterPojo
	 * @return List<CountryMasterPojo>
	 * @throws BusinessException
	 */
	@Override
	public List<CountryMasterPojo> getAllCountries(
			CountryMasterPojo countryMasterPojo) throws BusinessException {
		List<CountryMasterPojo> countryMasterPojoList = null;
		try {
			countryMasterPojoList = baseDAO.findAll(countryMasterPojo);
		} catch (DAOException e) {
			throw new BusinessException(e);
		}
		return countryMasterPojoList;
	}

	/**
	 * Method to send a an verification Email Message to Supplier User
	 * 
	 * @param supplierUsersPojo
	 * @throws BusinessException
	 * @throws TechnicalException
	 */
	@Override
	public TransactionStatus sendEmail(SupplierUsersPojo supplierUsersPojo)
			throws BusinessException, SystemConfigurationException,
			TechnicalException {
		TransactionStatus transactionStatus = new TransactionStatus(
				EnumTransactionStatus.BUSINESS_FLOW_FAIL.ordinal());
		String email = supplierUsersPojo.getUserMasterPojo().getEmail();

		try {
			if (Boolean.TRUE.toString().equals(
					supplierUsersPojo.getUserMasterPojo().getEmailVerfied())) {
				throw new BusinessException(ApplicationErrorCodes.BEC_1000006,
						null, TechnicalException.SEVERITY_WARN,
						new Object[] { email });
			}
			List<String> toEmailAddressList = new ArrayList<String>();
			toEmailAddressList.add(email);
			String subject = MessageBoardUtil.getValue(
					FacesContext.getCurrentInstance(),
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					ApplicationConstants.SUPPLIER_EMAIL_VERFICATION_SUBJECT,
					null);
			Object args[] = {
					supplierUsersPojo.getSupplierMasterPojo()
							.getCompanyMasterPojo().getCompanyName(), email };
			StringBuffer messageContentBuffer = new StringBuffer();
			messageContentBuffer.append(MessageBoardUtil.getValue(
					FacesContext.getCurrentInstance(),
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					ApplicationConstants.SUPPLIER_EMAIL_VERFICATION_MESSAGE,
					args));
			// Prepare Key Data
			JSONObject jsonMessage = new JSONObject();
			jsonMessage.put("ACTOR", EnumActor.SUPPLIER_USER.getActor());
			jsonMessage.put("SUPPLIER_USER_ID", supplierUsersPojo
					.getSupplierUserId().toString());
			jsonMessage.put("EMAIL", email);
			jsonMessage.put("TOKEN_TIMESTAMP",
					DateUtils.getCurrentDateTimeInternalFormat());
			String hexData = CommonUtils.convertJSONtoHex(jsonMessage);
			// Prepare the verify Link Anchor
			StringBuffer verifyLinkHref = new StringBuffer();
			verifyLinkHref.append("<a href='");
			verifyLinkHref
					.append(SystemConfig
							.getProperty(ApplicationConstants.SUPPLIER_EMAIL_VERFICATION_VERIFY_LINK));
			verifyLinkHref.append("?verifytoken=").append(hexData);
			verifyLinkHref.append("'>");
			verifyLinkHref
					.append(MessageBoardUtil.getValue(
							FacesContext.getCurrentInstance(),
							"commonMsgs",
							ApplicationConstants.SUPPLIER_EMAIL_VERFICATION_VERIFY_LINK_TEXT,
							null));
			verifyLinkHref.append("</a>");
			messageContentBuffer.append(verifyLinkHref.toString());
			EmailSender.sendMail(toEmailAddressList, null, subject,
					messageContentBuffer.toString(),
					ApplicationConstants.MAIL_TYPE_HTML);
			transactionStatus
					.setStatus(EnumTransactionStatus.BUSINESS_FLOW_SUCCESS
							.ordinal());
			MessageBoardUtil.publishMessage(
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					BaseException.SEVERITY_INFO, "messageBoardId",
					ApplicationConstants.SEND_EMAIL_VERIFICATION_SUCCESSFULL,
					new Object[] { email });
		} catch (EmailException e) {
			log.error(e);
			throw new TechnicalException("TEC_1000001", e,
					TechnicalException.SEVERITY_ERROR, new Object[] { email });
		} catch (SystemConfigurationException e) {
			log.error(e);
			throw e;
		} catch (JSONException e) {
			log.error(e);
			throw new TechnicalException("TEC_1000001", e,
					TechnicalException.SEVERITY_ERROR, new Object[] { email });
		}
		return transactionStatus;
	}

	/**
	 * Method to activate the Email Address
	 * 
	 * @param token
	 * @throws BusinessException
	 * @throws TechnicalException
	 */
	@Override
	public TransactionStatus activateEmail(String token)
			throws BusinessException, TechnicalException {
		TransactionStatus transactionStatus = new TransactionStatus(
				EnumTransactionStatus.UPDATE_FAIL.ordinal());
		try {
			JSONObject tokenJSON = CommonUtils.convertHextoJSON(token);
			if (tokenJSON == null) {
				throw new TechnicalException(ApplicationErrorCodes.TEC_1000003,
						null, TechnicalException.SEVERITY_ERROR, null);
			}
			String actor = (String) tokenJSON.get("ACTOR");
			String email = (String) tokenJSON.get("EMAIL");
			String timeStamp = (String) tokenJSON.get("TOKEN_TIMESTAMP");
			if (EnumActor.SUPPLIER_USER.getActor().equals(actor)) {
				String supplierUserId = (String) tokenJSON
						.get("SUPPLIER_USER_ID");
				SupplierUsersPojo supplierUsersPojo = (SupplierUsersPojo) baseDAO
						.findActiveById(new SupplierUsersPojo(),
								Long.parseLong(supplierUserId));
				if (supplierUsersPojo != null
						&& supplierUsersPojo.isPersisted()) {
					if (supplierUsersPojo.getUserMasterPojo().getEmail()
							.equals(email)) {
						if (Boolean.TRUE.toString().equals(
								supplierUsersPojo.getUserMasterPojo()
										.getEmailVerfied())) {
							// If Email Account already verified then no need to
							// verify again
							throw new BusinessException(
									ApplicationErrorCodes.BEC_1000006, null,
									TechnicalException.SEVERITY_WARN,
									new Object[] { email });
						} else {
							supplierUsersPojo.getUserMasterPojo()
									.setEmailVerfied(Boolean.TRUE.toString());
							transactionStatus = baseDAO
									.update(supplierUsersPojo
											.getUserMasterPojo());
							// Update Message Board with status
							if (EnumTransactionStatus.UPDATE_SUCCESS.status() == transactionStatus
									.getStatus().intValue()) {
								MessageBoardUtil
										.publishMessage(
												ApplicationConstants.RESOURCE_BUNDLE_COMMON,
												BaseException.SEVERITY_INFO,
												"messageBoardId",
												ApplicationConstants.EMAIL_VERIFICATION_SUCESSFULL,
												new Object[] { email });
							} else {
								MessageBoardUtil
										.publishMessage(
												ApplicationConstants.RESOURCE_BUNDLE_COMMON,
												BaseException.SEVERITY_ERROR,
												"messageBoardId",
												ApplicationConstants.EMAIL_VERIFICATION_FAIL,
												new Object[] { email });
							}
						}
					} else {
						log.error("The Supplier Account Associated with this Email Adress from the token no longer exists in the database");
						throw new BusinessException(
								ApplicationErrorCodes.BEC_1000005, null,
								BaseException.SEVERITY_ERROR,
								new Object[] { email });
					}
				} else {
					log.error("The Email Adress from the token is not same as what has been registered");
					throw new BusinessException(
							ApplicationErrorCodes.BEC_1000004, null,
							BaseException.SEVERITY_ERROR,
							new Object[] { email });
				}
			} else if (EnumActor.BUYER_USER.getActor().equals(actor)) {
				String buyerUserId = (String) tokenJSON.get("BUYER_USER_ID");
			}
		} catch (JSONException e) {
			log.error(e);
			throw new TechnicalException(ApplicationErrorCodes.TEC_1000002, e,
					TechnicalException.SEVERITY_ERROR, null);
		} catch (NumberFormatException e) {
			log.error(e);
		} catch (DAOException e) {
			log.error(e);
		}
		return transactionStatus;
	}

	@Override
	public TransactionStatus sendEmail(BuyerUsersPojo buyerUsersPojo) throws BusinessException,
			SystemConfigurationException, TechnicalException
	{
		TransactionStatus transactionStatus = new TransactionStatus(
				EnumTransactionStatus.BUSINESS_FLOW_FAIL.ordinal());
		String email = buyerUsersPojo.getUserMasterPojo().getEmail();

		try {
			if (Boolean.TRUE.toString().equals(
					buyerUsersPojo.getUserMasterPojo().getEmailVerfied())) {
				throw new BusinessException(ApplicationErrorCodes.BEC_1000006,
						null, TechnicalException.SEVERITY_WARN,
						new Object[] { email });
			}
			List<String> toEmailAddressList = new ArrayList<String>();
			toEmailAddressList.add(email);
			String subject = MessageBoardUtil.getValue(
					FacesContext.getCurrentInstance(),
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					ApplicationConstants.BUYER_EMAIL_VERFICATION_SUBJECT,
					null);
			Object args[] = {
					buyerUsersPojo.getBuyerMasterPojo()
							.getCompanyMasterPojo().getCompanyName(), email };
			StringBuffer messageContentBuffer = new StringBuffer();
			messageContentBuffer.append(MessageBoardUtil.getValue(
					FacesContext.getCurrentInstance(),
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					ApplicationConstants.BUYER_EMAIL_VERFICATION_MESSAGE,
					args));
			// Prepare Key Data
			JSONObject jsonMessage = new JSONObject();
			jsonMessage.put("ACTOR", EnumActor.BUYER_USER.getActor());
			jsonMessage.put("BUYER_USER_ID", buyerUsersPojo
					.getBuyerUserId().toString());
			jsonMessage.put("EMAIL", email);
			jsonMessage.put("TOKEN_TIMESTAMP",
					DateUtils.getCurrentDateTimeInternalFormat());
			String hexData = CommonUtils.convertJSONtoHex(jsonMessage);
			// Prepare the verify Link Anchor
			StringBuffer verifyLinkHref = new StringBuffer();
			verifyLinkHref.append("<a href='");
			verifyLinkHref
					.append(SystemConfig
							.getProperty(ApplicationConstants.BUYER_EMAIL_VERFICATION_VERIFY_LINK));
			verifyLinkHref.append("?verifytoken=").append(hexData);
			verifyLinkHref.append("'>");
			verifyLinkHref
					.append(MessageBoardUtil.getValue(
							FacesContext.getCurrentInstance(),
							"commonMsgs",
							ApplicationConstants.BUYER_EMAIL_VERFICATION_VERIFY_LINK_TEXT,
							null));
			verifyLinkHref.append("</a>");
			messageContentBuffer.append(verifyLinkHref.toString());
			EmailSender.sendMail(toEmailAddressList, null, subject,
					messageContentBuffer.toString(),
					ApplicationConstants.MAIL_TYPE_HTML);
			transactionStatus
					.setStatus(EnumTransactionStatus.BUSINESS_FLOW_SUCCESS
							.ordinal());
			MessageBoardUtil.publishMessage(
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					BaseException.SEVERITY_INFO, "messageBoardId",
					ApplicationConstants.SEND_EMAIL_VERIFICATION_SUCCESSFULL,
					new Object[] { email });
		} catch (EmailException e) {
			log.error(e);
			throw new TechnicalException("TEC_1000001", e,
					TechnicalException.SEVERITY_ERROR, new Object[] { email });
		} catch (SystemConfigurationException e) {
			log.error(e);
			throw e;
		} catch (JSONException e) {
			log.error(e);
			throw new TechnicalException("TEC_1000001", e,
					TechnicalException.SEVERITY_ERROR, new Object[] { email });
		}
		return transactionStatus;
	}

	/**
	 * Method to send a an verification Email Message to System User
	 * 
	 * @param systemUserPojo
	 * @throws BusinessException
	 * @throws SystemConfigurationException
	 * @throws TechnicalException
	 */
	@Override
	public TransactionStatus sendEmail(SystemUsersPojo systemUsersPojo)
			throws BusinessException, SystemConfigurationException,
			TechnicalException {
		TransactionStatus transactionStatus = new TransactionStatus(
				EnumTransactionStatus.BUSINESS_FLOW_FAIL.ordinal());
		String email = systemUsersPojo.getUserMasterPojo().getEmail();

		try {
			if (Boolean.TRUE.toString().equals(
					systemUsersPojo.getUserMasterPojo().getEmailVerfied())) {
				throw new BusinessException(ApplicationErrorCodes.BEC_1000006,
						null, TechnicalException.SEVERITY_WARN,
						new Object[] { email });
			}
			List<String> toEmailAddressList = new ArrayList<String>();
			toEmailAddressList.add(email);
			String subject = MessageBoardUtil.getValue(
					FacesContext.getCurrentInstance(),
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					ApplicationConstants.SYSTEM_EMAIL_VERFICATION_SUBJECT,
					null);
			Object args[] = {
					systemUsersPojo.getCompanyMasterPojo().getCompanyName(), email };
			StringBuffer messageContentBuffer = new StringBuffer();
			messageContentBuffer.append(MessageBoardUtil.getValue(
					FacesContext.getCurrentInstance(),
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					ApplicationConstants.SYSTEM_EMAIL_VERFICATION_MESSAGE,
					args));
			// Prepare Key Data
			JSONObject jsonMessage = new JSONObject();
			jsonMessage.put("ACTOR", EnumActor.SYSTEM_USER.getActor());
			jsonMessage.put("SYSTEM_USER_ID", systemUsersPojo
					.getSystemUserId().toString());
			jsonMessage.put("EMAIL", email);
			jsonMessage.put("TOKEN_TIMESTAMP",
					DateUtils.getCurrentDateTimeInternalFormat());
			String hexData = CommonUtils.convertJSONtoHex(jsonMessage);
			// Prepare the verify Link Anchor
			StringBuffer verifyLinkHref = new StringBuffer();
			verifyLinkHref.append("<a href='");
			verifyLinkHref
					.append(SystemConfig
							.getProperty(ApplicationConstants.SUPPLIER_EMAIL_VERFICATION_VERIFY_LINK));
			verifyLinkHref.append("?verifytoken=").append(hexData);
			verifyLinkHref.append("'>");
			verifyLinkHref
					.append(MessageBoardUtil.getValue(
							FacesContext.getCurrentInstance(),
							"commonMsgs",
							ApplicationConstants.SUPPLIER_EMAIL_VERFICATION_VERIFY_LINK_TEXT,
							null));
			verifyLinkHref.append("</a>");
			messageContentBuffer.append(verifyLinkHref.toString());
			EmailSender.sendMail(toEmailAddressList, null, subject,
					messageContentBuffer.toString(),
					ApplicationConstants.MAIL_TYPE_HTML);
			transactionStatus
					.setStatus(EnumTransactionStatus.BUSINESS_FLOW_SUCCESS
							.ordinal());
			MessageBoardUtil.publishMessage(
					ApplicationConstants.RESOURCE_BUNDLE_COMMON,
					BaseException.SEVERITY_INFO, "messageBoardId",
					ApplicationConstants.SEND_EMAIL_VERIFICATION_SUCCESSFULL,
					new Object[] { email });
		} catch (EmailException e) {
			log.error(e);
			throw new TechnicalException("TEC_1000001", e,
					TechnicalException.SEVERITY_ERROR, new Object[] { email });
		} catch (SystemConfigurationException e) {
			log.error(e);
			throw e;
		} catch (JSONException e) {
			log.error(e);
			throw new TechnicalException("TEC_1000001", e,
					TechnicalException.SEVERITY_ERROR, new Object[] { email });
		}
		return transactionStatus;
	}
}
